home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Games / Doom / ADoom-0.8 / ADoom_src / i_video.c < prev    next >
C/C++ Source or Header  |  1998-06-24  |  23KB  |  1,051 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    DOOM graphics stuff for X11, UNIX.
  21. //
  22. //-----------------------------------------------------------------------------
  23.  
  24. static const char
  25. rcsid[] = "$Id: i_x.c,v 1.6 1997/02/03 22:45:10 b1 Exp $";
  26.  
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <sys/ipc.h>
  30. #include <sys/shm.h>
  31.  
  32. #include <X11/Xlib.h>
  33. #include <X11/Xutil.h>
  34. #include <X11/keysym.h>
  35.  
  36. #include <X11/extensions/XShm.h>
  37. // Had to dig up XShm.c for this one.
  38. // It is in the libXext, but not in the XFree86 headers.
  39. #ifdef LINUX
  40. int XShmGetEventBase( Display* dpy ); // problems with g++?
  41. #endif
  42.  
  43. #include <stdarg.h>
  44. #include <sys/time.h>
  45. #include <sys/types.h>
  46. #include <sys/socket.h>
  47.  
  48. #include <netinet/in.h>
  49. #include <errnos.h>
  50. #include <signal.h>
  51.  
  52. #include "doomstat.h"
  53. #include "i_system.h"
  54. #include "v_video.h"
  55. #include "m_argv.h"
  56. #include "d_main.h"
  57.  
  58. #include "doomdef.h"
  59.  
  60. #define POINTER_WARP_COUNTDOWN    1
  61.  
  62. Display*    X_display=0;
  63. Window        X_mainWindow;
  64. Colormap    X_cmap;
  65. Visual*        X_visual;
  66. GC        X_gc;
  67. XEvent        X_event;
  68. int        X_screen;
  69. XVisualInfo    X_visualinfo;
  70. XImage*        image;
  71. int        X_width;
  72. int        X_height;
  73.  
  74. // MIT SHared Memory extension.
  75. boolean        doShm;
  76.  
  77. XShmSegmentInfo    X_shminfo;
  78. int        X_shmeventtype;
  79.  
  80. // Fake mouse handling.
  81. // This cannot work properly w/o DGA.
  82. // Needs an invisible mouse cursor at least.
  83. boolean        grabMouse;
  84. int        doPointerWarp = POINTER_WARP_COUNTDOWN;
  85.  
  86. // Blocky mode,
  87. // replace each 320x200 pixel with multiply*multiply pixels.
  88. // According to Dave Taylor, it still is a bonehead thing
  89. // to use ....
  90. static int    multiply=1;
  91.  
  92.  
  93. //
  94. //  Translates the key currently in X_event
  95. //
  96.  
  97. int xlatekey(void)
  98. {
  99.  
  100.     int rc;
  101.  
  102.     switch(rc = XKeycodeToKeysym(X_display, X_event.xkey.keycode, 0))
  103.     {
  104.       case XK_Left:    rc = KEY_LEFTARROW;    break;
  105.       case XK_Right:    rc = KEY_RIGHTARROW;    break;
  106.       case XK_Down:    rc = KEY_DOWNARROW;    break;
  107.       case XK_Up:    rc = KEY_UPARROW;    break;
  108.       case XK_Escape:    rc = KEY_ESCAPE;    break;
  109.       case XK_Return:    rc = KEY_ENTER;        break;
  110.       case XK_Tab:    rc = KEY_TAB;        break;
  111.       case XK_F1:    rc = KEY_F1;        break;
  112.       case XK_F2:    rc = KEY_F2;        break;
  113.       case XK_F3:    rc = KEY_F3;        break;
  114.       case XK_F4:    rc = KEY_F4;        break;
  115.       case XK_F5:    rc = KEY_F5;        break;
  116.       case XK_F6:    rc = KEY_F6;        break;
  117.       case XK_F7:    rc = KEY_F7;        break;
  118.       case XK_F8:    rc = KEY_F8;        break;
  119.       case XK_F9:    rc = KEY_F9;        break;
  120.       case XK_F10:    rc = KEY_F10;        break;
  121.       case XK_F11:    rc = KEY_F11;        break;
  122.       case XK_F12:    rc = KEY_F12;        break;
  123.     
  124.       case XK_BackSpace:
  125.       case XK_Delete:    rc = KEY_BACKSPACE;    break;
  126.  
  127.       case XK_Pause:    rc = KEY_PAUSE;        break;
  128.  
  129.       case XK_KP_Equal:
  130.       case XK_equal:    rc = KEY_EQUALS;    break;
  131.  
  132.       case XK_KP_Subtract:
  133.       case XK_minus:    rc = KEY_MINUS;        break;
  134.  
  135.       case XK_Shift_L:
  136.       case XK_Shift_R:
  137.     rc = KEY_RSHIFT;
  138.     break;
  139.     
  140.       case XK_Control_L:
  141.       case XK_Control_R:
  142.     rc = KEY_RCTRL;
  143.     break;
  144.     
  145.       case XK_Alt_L:
  146.       case XK_Meta_L:
  147.       case XK_Alt_R:
  148.       case XK_Meta_R:
  149.     rc = KEY_RALT;
  150.     break;
  151.     
  152.       default:
  153.     if (rc >= XK_space && rc <= XK_asciitilde)
  154.         rc = rc - XK_space + ' ';
  155.     if (rc >= 'A' && rc <= 'Z')
  156.         rc = rc - 'A' + 'a';
  157.     break;
  158.     }
  159.  
  160.     return rc;
  161.  
  162. }
  163.  
  164. void I_ShutdownGraphics(void)
  165. {
  166.   // Detach from X server
  167.   if (!XShmDetach(X_display, &X_shminfo))
  168.         I_Error("XShmDetach() failed in I_ShutdownGraphics()");
  169.  
  170.   // Release shared memory.
  171.   shmdt(X_shminfo.shmaddr);
  172.   shmctl(X_shminfo.shmid, IPC_RMID, 0);
  173.  
  174.   // Paranoia.
  175.   image->data = NULL;
  176. }
  177.  
  178.  
  179.  
  180. //
  181. // I_StartFrame
  182. //
  183. void I_StartFrame (void)
  184. {
  185.     // er?
  186.  
  187. }
  188.  
  189. static int    lastmousex = 0;
  190. static int    lastmousey = 0;
  191. boolean        mousemoved = false;
  192. boolean        shmFinished;
  193.  
  194. void I_GetEvent(void)
  195. {
  196.  
  197.     event_t event;
  198.  
  199.     // put event-grabbing stuff in here
  200.     XNextEvent(X_display, &X_event);
  201.     switch (X_event.type)
  202.     {
  203.       case KeyPress:
  204.     event.type = ev_keydown;
  205.     event.data1 = xlatekey();
  206.     D_PostEvent(&event);
  207.     // fprintf(stderr, "k");
  208.     break;
  209.       case KeyRelease:
  210.     event.type = ev_keyup;
  211.     event.data1 = xlatekey();
  212.     D_PostEvent(&event);
  213.     // fprintf(stderr, "ku");
  214.     break;
  215.       case ButtonPress:
  216.     event.type = ev_mouse;
  217.     event.data1 =
  218.         (X_event.xbutton.state & Button1Mask)
  219.         | (X_event.xbutton.state & Button2Mask ? 2 : 0)
  220.         | (X_event.xbutton.state & Button3Mask ? 4 : 0)
  221.         | (X_event.xbutton.button == Button1)
  222.         | (X_event.xbutton.button == Button2 ? 2 : 0)
  223.         | (X_event.xbutton.button == Button3 ? 4 : 0);
  224.     event.data2 = event.data3 = 0;
  225.     D_PostEvent(&event);
  226.     // fprintf(stderr, "b");
  227.     break;
  228.       case ButtonRelease:
  229.     event.type = ev_mouse;
  230.     event.data1 =
  231.         (X_event.xbutton.state & Button1Mask)
  232.         | (X_event.xbutton.state & Button2Mask ? 2 : 0)
  233.         | (X_event.xbutton.state & Button3Mask ? 4 : 0);
  234.     // suggest parentheses around arithmetic in operand of |
  235.     event.data1 =
  236.         event.data1
  237.         ^ (X_event.xbutton.button == Button1 ? 1 : 0)
  238.         ^ (X_event.xbutton.button == Button2 ? 2 : 0)
  239.         ^ (X_event.xbutton.button == Button3 ? 4 : 0);
  240.     event.data2 = event.data3 = 0;
  241.     D_PostEvent(&event);
  242.     // fprintf(stderr, "bu");
  243.     break;
  244.       case MotionNotify:
  245.     event.type = ev_mouse;
  246.     event.data1 =
  247.         (X_event.xmotion.state & Button1Mask)
  248.         | (X_event.xmotion.state & Button2Mask ? 2 : 0)
  249.         | (X_event.xmotion.state & Button3Mask ? 4 : 0);
  250.     event.data2 = (X_event.xmotion.x - lastmousex) << 2;
  251.     event.data3 = (lastmousey - X_event.xmotion.y) << 2;
  252.  
  253.     if (event.data2 || event.data3)
  254.     {
  255.         lastmousex = X_event.xmotion.x;
  256.         lastmousey = X_event.xmotion.y;
  257.         if (X_event.xmotion.x != X_width/2 &&
  258.         X_event.xmotion.y != X_height/2)
  259.         {
  260.         D_PostEvent(&event);
  261.         // fprintf(stderr, "m");
  262.         mousemoved = false;
  263.         } else
  264.         {
  265.         mousemoved = true;
  266.         }
  267.     }
  268.     break;
  269.     
  270.       case Expose:
  271.       case ConfigureNotify:
  272.     break;
  273.     
  274.       default:
  275.     if (doShm && X_event.type == X_shmeventtype) shmFinished = true;
  276.     break;
  277.     }
  278.  
  279. }
  280.  
  281. Cursor
  282. createnullcursor
  283. ( Display*    display,
  284.   Window    root )
  285. {
  286.     Pixmap cursormask;
  287.     XGCValues xgc;
  288.     GC gc;
  289.     XColor dummycolour;
  290.     Cursor cursor;
  291.  
  292.     cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
  293.     xgc.function = GXclear;
  294.     gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
  295.     XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
  296.     dummycolour.pixel = 0;
  297.     dummycolour.red = 0;
  298.     dummycolour.flags = 04;
  299.     cursor = XCreatePixmapCursor(display, cursormask, cursormask,
  300.                  &dummycolour,&dummycolour, 0,0);
  301.     XFreePixmap(display,cursormask);
  302.     XFreeGC(display,gc);
  303.     return cursor;
  304. }
  305.  
  306. //
  307. // I_StartTic
  308. //
  309. void I_StartTic (void)
  310. {
  311.  
  312.     if (!X_display)
  313.     return;
  314.  
  315.     while (XPending(X_display))
  316.     I_GetEvent();
  317.  
  318.     // Warp the pointer back to the middle of the window
  319.     //  or it will wander off - that is, the game will
  320.     //  loose input focus within X11.
  321.     if (grabMouse)
  322.     {
  323.     if (!--doPointerWarp)
  324.     {
  325.         XWarpPointer( X_display,
  326.               None,
  327.               X_mainWindow,
  328.               0, 0,
  329.               0, 0,
  330.               X_width/2, X_height/2);
  331.  
  332.         doPointerWarp = POINTER_WARP_COUNTDOWN;
  333.     }
  334.     }
  335.  
  336.     mousemoved = false;
  337.  
  338. }
  339.  
  340.  
  341. //
  342. // I_UpdateNoBlit
  343. //
  344. void I_UpdateNoBlit (void)
  345. {
  346.     // what is this?
  347. }
  348.  
  349. //
  350. // I_FinishUpdate
  351. //
  352. void I_FinishUpdate (void)
  353. {
  354.  
  355.     static int    lasttic;
  356.     int        tics;
  357.     int        i;
  358.     // UNUSED static unsigned char *bigscreen=0;
  359.  
  360.     // draws little dots on the bottom of the screen
  361.     if (devparm)
  362.     {
  363.  
  364.     i = I_GetTime();
  365.     tics = i - lasttic;
  366.     lasttic = i;
  367.     if (tics > 20) tics = 20;
  368.  
  369.     for (i=0 ; i<tics*2 ; i+=2)
  370.         screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0xff;
  371.     for ( ; i<20*2 ; i+=2)
  372.         screens[0][ (SCREENHEIGHT-1)*SCREENWIDTH + i] = 0x0;
  373.     
  374.     }
  375.  
  376.     // scales the screen size before blitting it
  377.     if (multiply == 2)
  378.     {
  379.     unsigned int *olineptrs[2];
  380.     unsigned int *ilineptr;
  381.     int x, y, i;
  382.     unsigned int twoopixels;
  383.     unsigned int twomoreopixels;
  384.     unsigned int fouripixels;
  385.  
  386.     ilineptr = (unsigned int *) (screens[0]);
  387.     for (i=0 ; i<2 ; i++)
  388.         olineptrs[i] = (unsigned int *) &image->data[i*X_width];
  389.  
  390.     y = SCREENHEIGHT;
  391.     while (y--)
  392.     {
  393.         x = SCREENWIDTH;
  394.         do
  395.         {
  396.         fouripixels = *ilineptr++;
  397.         twoopixels =    (fouripixels & 0xff000000)
  398.             |    ((fouripixels>>8) & 0xffff00)
  399.             |    ((fouripixels>>16) & 0xff);
  400.         twomoreopixels =    ((fouripixels<<16) & 0xff000000)
  401.             |    ((fouripixels<<8) & 0xffff00)
  402.             |    (fouripixels & 0xff);
  403. #ifdef __BIG_ENDIAN__
  404.         *olineptrs[0]++ = twoopixels;
  405.         *olineptrs[1]++ = twoopixels;
  406.         *olineptrs[0]++ = twomoreopixels;
  407.         *olineptrs[1]++ = twomoreopixels;
  408. #else
  409.         *olineptrs[0]++ = twomoreopixels;
  410.         *olineptrs[1]++ = twomoreopixels;
  411.         *olineptrs[0]++ = twoopixels;
  412.         *olineptrs[1]++ = twoopixels;
  413. #endif
  414.         } while (x-=4);
  415.         olineptrs[0] += X_width/4;
  416.         olineptrs[1] += X_width/4;
  417.     }
  418.  
  419.     }
  420.     else if (multiply == 3)
  421.     {
  422.     unsigned int *olineptrs[3];
  423.     unsigned int *ilineptr;
  424.     int x, y, i;
  425.     unsigned int fouropixels[3];
  426.     unsigned int fouripixels;
  427.  
  428.     ilineptr = (unsigned int *) (screens[0]);
  429.     for (i=0 ; i<3 ; i++)
  430.         olineptrs[i] = (unsigned int *) &image->data[i*X_width];
  431.  
  432.     y = SCREENHEIGHT;
  433.     while (y--)
  434.     {
  435.         x = SCREENWIDTH;
  436.         do
  437.         {
  438.         fouripixels = *ilineptr++;
  439.         fouropixels[0] = (fouripixels & 0xff000000)
  440.             |    ((fouripixels>>8) & 0xff0000)
  441.             |    ((fouripixels>>16) & 0xffff);
  442.         fouropixels[1] = ((fouripixels<<8) & 0xff000000)
  443.             |    (fouripixels & 0xffff00)
  444.             |    ((fouripixels>>8) & 0xff);
  445.         fouropixels[2] = ((fouripixels<<16) & 0xffff0000)
  446.             |    ((fouripixels<<8) & 0xff00)
  447.             |    (fouripixels & 0xff);
  448. #ifdef __BIG_ENDIAN__
  449.         *olineptrs[0]++ = fouropixels[0];
  450.         *olineptrs[1]++ = fouropixels[0];
  451.         *olineptrs[2]++ = fouropixels[0];
  452.         *olineptrs[0]++ = fouropixels[1];
  453.         *olineptrs[1]++ = fouropixels[1];
  454.         *olineptrs[2]++ = fouropixels[1];
  455.         *olineptrs[0]++ = fouropixels[2];
  456.         *olineptrs[1]++ = fouropixels[2];
  457.         *olineptrs[2]++ = fouropixels[2];
  458. #else
  459.         *olineptrs[0]++ = fouropixels[2];
  460.         *olineptrs[1]++ = fouropixels[2];
  461.         *olineptrs[2]++ = fouropixels[2];
  462.         *olineptrs[0]++ = fouropixels[1];
  463.         *olineptrs[1]++ = fouropixels[1];
  464.         *olineptrs[2]++ = fouropixels[1];
  465.         *olineptrs[0]++ = fouropixels[0];
  466.         *olineptrs[1]++ = fouropixels[0];
  467.         *olineptrs[2]++ = fouropixels[0];
  468. #endif
  469.         } while (x-=4);
  470.         olineptrs[0] += 2*X_width/4;
  471.         olineptrs[1] += 2*X_width/4;
  472.         olineptrs[2] += 2*X_width/4;
  473.     }
  474.  
  475.     }
  476.     else if (multiply == 4)
  477.     {
  478.     // Broken. Gotta fix this some day.
  479.     void Expand4(unsigned *, double *);
  480.       Expand4 ((unsigned *)(screens[0]), (double *) (image->data));
  481.     }
  482.  
  483.     if (doShm)
  484.     {
  485.  
  486.     if (!XShmPutImage(    X_display,
  487.                 X_mainWindow,
  488.                 X_gc,
  489.                 image,
  490.                 0, 0,
  491.                 0, 0,
  492.                 X_width, X_height,
  493.                 True ))
  494.         I_Error("XShmPutImage() failed\n");
  495.  
  496.     // wait for it to finish and processes all input events
  497.     shmFinished = false;
  498.     do
  499.     {
  500.         I_GetEvent();
  501.     } while (!shmFinished);
  502.  
  503.     }
  504.     else
  505.     {
  506.  
  507.     // draw the image
  508.     XPutImage(    X_display,
  509.             X_mainWindow,
  510.             X_gc,
  511.             image,
  512.             0, 0,
  513.             0, 0,
  514.             X_width, X_height );
  515.  
  516.     // sync up with server
  517.     XSync(X_display, False);
  518.  
  519.     }
  520.  
  521. }
  522.  
  523.  
  524. //
  525. // I_ReadScreen
  526. //
  527. void I_ReadScreen (byte* scr)
  528. {
  529.     memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
  530. }
  531.  
  532.  
  533. //
  534. // Palette stuff.
  535. //
  536. static XColor    colors[256];
  537.  
  538. void UploadNewPalette(Colormap cmap, byte *palette)
  539. {
  540.  
  541.     register int    i;
  542.     register int    c;
  543.     static boolean    firstcall = true;
  544.  
  545. #ifdef __cplusplus
  546.     if (X_visualinfo.c_class == PseudoColor && X_visualinfo.depth == 8)
  547. #else
  548.     if (X_visualinfo.class == PseudoColor && X_visualinfo.depth == 8)
  549. #endif
  550.     {
  551.         // initialize the colormap
  552.         if (firstcall)
  553.         {
  554.         firstcall = false;
  555.         for (i=0 ; i<256 ; i++)
  556.         {
  557.             colors[i].pixel = i;
  558.             colors[i].flags = DoRed|DoGreen|DoBlue;
  559.         }
  560.         }
  561.  
  562.         // set the X colormap entries
  563.         for (i=0 ; i<256 ; i++)
  564.         {
  565.         c = gammatable[usegamma][*palette++];
  566.         colors[i].red = (c<<8) + c;
  567.         c = gammatable[usegamma][*palette++];
  568.         colors[i].green = (c<<8) + c;
  569.         c = gammatable[usegamma][*palette++];
  570.         colors[i].blue = (c<<8) + c;
  571.         }
  572.  
  573.         // store the colors to the current colormap
  574.         XStoreColors(X_display, cmap, colors, 256);
  575.  
  576.     }
  577. }
  578.  
  579. //
  580. // I_SetPalette
  581. //
  582. void I_SetPalette (byte* palette)
  583. {
  584.     UploadNewPalette(X_cmap, palette);
  585. }
  586.  
  587.  
  588. //
  589. // This function is probably redundant,
  590. //  if XShmDetach works properly.
  591. // ddt never detached the XShm memory,
  592. //  thus there might have been stale
  593. //  handles accumulating.
  594. //
  595. void grabsharedmemory(int size)
  596. {
  597.  
  598.   int            key = ('d'<<24) | ('o'<<16) | ('o'<<8) | 'm';
  599.   struct shmid_ds    shminfo;
  600.   int            minsize = 320*200;
  601.   int            id;
  602.   int            rc;
  603.   // UNUSED int done=0;
  604.   int            pollution=5;
  605.   
  606.   // try to use what was here before
  607.   do
  608.   {
  609.     id = shmget((key_t) key, minsize, 0777); // just get the id
  610.     if (id != -1)
  611.     {
  612.       rc=shmctl(id, IPC_STAT, &shminfo); // get stats on it
  613.       if (!rc) 
  614.       {
  615.     if (shminfo.shm_nattch)
  616.     {
  617.       fprintf(stderr, "User %d appears to be running "
  618.           "DOOM.  Is that wise?\n", shminfo.shm_cpid);
  619.       key++;
  620.     }
  621.     else
  622.     {
  623.       if (getuid() == shminfo.shm_perm.cuid)
  624.       {
  625.         rc = shmctl(id, IPC_RMID, 0);
  626.         if (!rc)
  627.           fprintf(stderr,
  628.               "Was able to kill my old shared memory\n");
  629.         else
  630.           I_Error("Was NOT able to kill my old shared memory");
  631.         
  632.         id = shmget((key_t)key, size, IPC_CREAT|0777);
  633.         if (id==-1)
  634.           I_Error("Could not get shared memory");
  635.         
  636.         rc=shmctl(id, IPC_STAT, &shminfo);
  637.         
  638.         break;
  639.         
  640.       }
  641.       if (size >= shminfo.shm_segsz)
  642.       {
  643.         fprintf(stderr,
  644.             "will use %d's stale shared memory\n",
  645.             shminfo.shm_cpid);
  646.         break;
  647.       }
  648.       else
  649.       {
  650.         fprintf(stderr,
  651.             "warning: can't use stale "
  652.             "shared memory belonging to id %d, "
  653.             "key=0x%x\n",
  654.             shminfo.shm_cpid, key);
  655.         key++;
  656.       }
  657.     }
  658.       }
  659.       else
  660.       {
  661.     I_Error("could not get stats on key=%d", key);
  662.       }
  663.     }
  664.     else
  665.     {
  666.       id = shmget((key_t)key, size, IPC_CREAT|0777);
  667.       if (id==-1)
  668.       {
  669.     extern int errno;
  670.     fprintf(stderr, "errno=%d\n", errno);
  671.     I_Error("Could not get any shared memory");
  672.       }
  673.       break;
  674.     }
  675.   } while (--pollution);
  676.   
  677.   if (!pollution)
  678.   {
  679.     I_Error("Sorry, system too polluted with stale "
  680.         "shared memory segments.\n");
  681.     }    
  682.   
  683.   X_shminfo.shmid = id;
  684.   
  685.   // attach to the shared memory segment
  686.   image->data = X_shminfo.shmaddr = shmat(id, 0, 0);
  687.   
  688.   fprintf(stderr, "shared memory id=%d, addr=0x%x\n", id,
  689.       (int) (image->data));
  690. }
  691.  
  692. void I_InitGraphics(void)
  693. {
  694.  
  695.     char*        displayname;
  696.     char*        d;
  697.     int            n;
  698.     int            pnum;
  699.     int            x=0;
  700.     int            y=0;
  701.     
  702.     // warning: char format, different type arg
  703.     char        xsign=' ';
  704.     char        ysign=' ';
  705.     
  706.     int            oktodraw;
  707.     unsigned long    attribmask;
  708.     XSetWindowAttributes attribs;
  709.     XGCValues        xgcvalues;
  710.     int            valuemask;
  711.     static int        firsttime=1;
  712.  
  713.     if (!firsttime)
  714.     return;
  715.     firsttime = 0;
  716.  
  717.     signal(SIGINT, (void (*)(int)) I_Quit);
  718.  
  719.     if (M_CheckParm("-2"))
  720.     multiply = 2;
  721.  
  722.     if (M_CheckParm("-3"))
  723.     multiply = 3;
  724.  
  725.     if (M_CheckParm("-4"))
  726.     multiply = 4;
  727.  
  728.     X_width = SCREENWIDTH * multiply;
  729.     X_height = SCREENHEIGHT * multiply;
  730.  
  731.     // check for command-line display name
  732.     if ( (pnum=M_CheckParm("-disp")) ) // suggest parentheses around assignment
  733.     displayname = myargv[pnum+1];
  734.     else
  735.     displayname = 0;
  736.  
  737.     // check if the user wants to grab the mouse (quite unnice)
  738.     grabMouse = !!M_CheckParm("-grabmouse");
  739.  
  740.     // check for command-line geometry
  741.     if ( (pnum=M_CheckParm("-geom")) ) // suggest parentheses around assignment
  742.     {
  743.     // warning: char format, different type arg 3,5
  744.     n = sscanf(myargv[pnum+1], "%c%d%c%d", &xsign, &x, &ysign, &y);
  745.     
  746.     if (n==2)
  747.         x = y = 0;
  748.     else if (n==6)
  749.     {
  750.         if (xsign == '-')
  751.         x = -x;
  752.         if (ysign == '-')
  753.         y = -y;
  754.     }
  755.     else
  756.         I_Error("bad -geom parameter");
  757.     }
  758.  
  759.     // open the display
  760.     X_display = XOpenDisplay(displayname);
  761.     if (!X_display)
  762.     {
  763.     if (displayname)
  764.         I_Error("Could not open display [%s]", displayname);
  765.     else
  766.         I_Error("Could not open display (DISPLAY=[%s])", getenv("DISPLAY"));
  767.     }
  768.  
  769.     // use the default visual 
  770.     X_screen = DefaultScreen(X_display);
  771.     if (!XMatchVisualInfo(X_display, X_screen, 8, PseudoColor, &X_visualinfo))
  772.     I_Error("xdoom currently only supports 256-color PseudoColor screens");
  773.     X_visual = X_visualinfo.visual;
  774.  
  775.     // check for the MITSHM extension
  776.     doShm = XShmQueryExtension(X_display);
  777.  
  778.     // even if it's available, make sure it's a local connection
  779.     if (doShm)
  780.     {
  781.     if (!displayname) displayname = (char *) getenv("DISPLAY");
  782.     if (displayname)
  783.     {
  784.         d = displayname;
  785.         while (*d && (*d != ':')) d++;
  786.         if (*d) *d = 0;
  787.         if (!(!strcasecmp(displayname, "unix") || !*displayname)) doShm = false;
  788.     }
  789.     }
  790.  
  791.     fprintf(stderr, "Using MITSHM extension\n");
  792.  
  793.     // create the colormap
  794.     X_cmap = XCreateColormap(X_display, RootWindow(X_display,
  795.                            X_screen), X_visual, AllocAll);
  796.  
  797.     // setup attributes for main window
  798.     attribmask = CWEventMask | CWColormap | CWBorderPixel;
  799.     attribs.event_mask =
  800.     KeyPressMask
  801.     | KeyReleaseMask
  802.     // | PointerMotionMask | ButtonPressMask | ButtonReleaseMask
  803.     | ExposureMask;
  804.  
  805.     attribs.colormap = X_cmap;
  806.     attribs.border_pixel = 0;
  807.  
  808.     // create the main window
  809.     X_mainWindow = XCreateWindow(    X_display,
  810.                     RootWindow(X_display, X_screen),
  811.                     x, y,
  812.                     X_width, X_height,
  813.                     0, // borderwidth
  814.                     8, // depth
  815.                     InputOutput,
  816.                     X_visual,
  817.                     attribmask,
  818.                     &attribs );
  819.  
  820.     XDefineCursor(X_display, X_mainWindow,
  821.           createnullcursor( X_display, X_mainWindow ) );
  822.  
  823.     // create the GC
  824.     valuemask = GCGraphicsExposures;
  825.     xgcvalues.graphics_exposures = False;
  826.     X_gc = XCreateGC(    X_display,
  827.               X_mainWindow,
  828.               valuemask,
  829.               &xgcvalues );
  830.  
  831.     // map the window
  832.     XMapWindow(X_display, X_mainWindow);
  833.  
  834.     // wait until it is OK to draw
  835.     oktodraw = 0;
  836.     while (!oktodraw)
  837.     {
  838.     XNextEvent(X_display, &X_event);
  839.     if (X_event.type == Expose
  840.         && !X_event.xexpose.count)
  841.     {
  842.         oktodraw = 1;
  843.     }
  844.     }
  845.  
  846.     // grabs the pointer so it is restricted to this window
  847.     if (grabMouse)
  848.     XGrabPointer(X_display, X_mainWindow, True,
  849.              ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
  850.              GrabModeAsync, GrabModeAsync,
  851.              X_mainWindow, None, CurrentTime);
  852.  
  853.     if (doShm)
  854.     {
  855.  
  856.     X_shmeventtype = XShmGetEventBase(X_display) + ShmCompletion;
  857.  
  858.     // create the image
  859.     image = XShmCreateImage(    X_display,
  860.                     X_visual,
  861.                     8,
  862.                     ZPixmap,
  863.                     0,
  864.                     &X_shminfo,
  865.                     X_width,
  866.                     X_height );
  867.  
  868.     grabsharedmemory(image->bytes_per_line * image->height);
  869.  
  870.  
  871.     // UNUSED
  872.     // create the shared memory segment
  873.     // X_shminfo.shmid = shmget (IPC_PRIVATE,
  874.     // image->bytes_per_line * image->height, IPC_CREAT | 0777);
  875.     // if (X_shminfo.shmid < 0)
  876.     // {
  877.     // perror("");
  878.     // I_Error("shmget() failed in InitGraphics()");
  879.     // }
  880.     // fprintf(stderr, "shared memory id=%d\n", X_shminfo.shmid);
  881.     // attach to the shared memory segment
  882.     // image->data = X_shminfo.shmaddr = shmat(X_shminfo.shmid, 0, 0);
  883.     
  884.  
  885.     if (!image->data)
  886.     {
  887.         perror("");
  888.         I_Error("shmat() failed in InitGraphics()");
  889.     }
  890.  
  891.     // get the X server to attach to it
  892.     if (!XShmAttach(X_display, &X_shminfo))
  893.         I_Error("XShmAttach() failed in InitGraphics()");
  894.  
  895.     }
  896.     else
  897.     {
  898.     image = XCreateImage(    X_display,
  899.                     X_visual,
  900.                     8,
  901.                     ZPixmap,
  902.                     0,
  903.                     (char*)malloc(X_width * X_height),
  904.                     X_width, X_height,
  905.                     8,
  906.                     X_width );
  907.  
  908.     }
  909.  
  910.     if (multiply == 1)
  911.     screens[0] = (unsigned char *) (image->data);
  912.     else
  913.     screens[0] = (unsigned char *) malloc (SCREENWIDTH * SCREENHEIGHT);
  914.  
  915. }
  916.  
  917.  
  918. unsigned    exptable[256];
  919.  
  920. void InitExpand (void)
  921. {
  922.     int        i;
  923.     
  924.     for (i=0 ; i<256 ; i++)
  925.     exptable[i] = i | (i<<8) | (i<<16) | (i<<24);
  926. }
  927.  
  928. double        exptable2[256*256];
  929.  
  930. void InitExpand2 (void)
  931. {
  932.     int        i;
  933.     int        j;
  934.     // UNUSED unsigned    iexp, jexp;
  935.     double*    exp;
  936.     union
  937.     {
  938.     double         d;
  939.     unsigned    u[2];
  940.     } pixel;
  941.     
  942.     printf ("building exptable2...\n");
  943.     exp = exptable2;
  944.     for (i=0 ; i<256 ; i++)
  945.     {
  946.     pixel.u[0] = i | (i<<8) | (i<<16) | (i<<24);
  947.     for (j=0 ; j<256 ; j++)
  948.     {
  949.         pixel.u[1] = j | (j<<8) | (j<<16) | (j<<24);
  950.         *exp++ = pixel.d;
  951.     }
  952.     }
  953.     printf ("done.\n");
  954. }
  955.  
  956. int    inited;
  957.  
  958. void
  959. Expand4
  960. ( unsigned*    lineptr,
  961.   double*    xline )
  962. {
  963.     double    dpixel;
  964.     unsigned    x;
  965.     unsigned     y;
  966.     unsigned    fourpixels;
  967.     unsigned    step;
  968.     double*    exp;
  969.     
  970.     exp = exptable2;
  971.     if (!inited)
  972.     {
  973.     inited = 1;
  974.     InitExpand2 ();
  975.     }
  976.         
  977.         
  978.     step = 3*SCREENWIDTH/2;
  979.     
  980.     y = SCREENHEIGHT-1;
  981.     do
  982.     {
  983.     x = SCREENWIDTH;
  984.  
  985.     do
  986.     {
  987.         fourpixels = lineptr[0];
  988.             
  989.         dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
  990.         xline[0] = dpixel;
  991.         xline[160] = dpixel;
  992.         xline[320] = dpixel;
  993.         xline[480] = dpixel;
  994.             
  995.         dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
  996.         xline[1] = dpixel;
  997.         xline[161] = dpixel;
  998.         xline[321] = dpixel;
  999.         xline[481] = dpixel;
  1000.  
  1001.         fourpixels = lineptr[1];
  1002.             
  1003.         dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
  1004.         xline[2] = dpixel;
  1005.         xline[162] = dpixel;
  1006.         xline[322] = dpixel;
  1007.         xline[482] = dpixel;
  1008.             
  1009.         dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
  1010.         xline[3] = dpixel;
  1011.         xline[163] = dpixel;
  1012.         xline[323] = dpixel;
  1013.         xline[483] = dpixel;
  1014.  
  1015.         fourpixels = lineptr[2];
  1016.             
  1017.         dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
  1018.         xline[4] = dpixel;
  1019.         xline[164] = dpixel;
  1020.         xline[324] = dpixel;
  1021.         xline[484] = dpixel;
  1022.             
  1023.         dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
  1024.         xline[5] = dpixel;
  1025.         xline[165] = dpixel;
  1026.         xline[325] = dpixel;
  1027.         xline[485] = dpixel;
  1028.  
  1029.         fourpixels = lineptr[3];
  1030.             
  1031.         dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff0000)>>13) );
  1032.         xline[6] = dpixel;
  1033.         xline[166] = dpixel;
  1034.         xline[326] = dpixel;
  1035.         xline[486] = dpixel;
  1036.             
  1037.         dpixel = *(double *)( (int)exp + ( (fourpixels&0xffff)<<3 ) );
  1038.         xline[7] = dpixel;
  1039.         xline[167] = dpixel;
  1040.         xline[327] = dpixel;
  1041.         xline[487] = dpixel;
  1042.  
  1043.         lineptr+=4;
  1044.         xline+=8;
  1045.     } while (x-=16);
  1046.     xline += step;
  1047.     } while (y--);
  1048. }
  1049.  
  1050.  
  1051.